#include <assert.h>
#include <stdio.h>

#include <iostream>
#include <typeinfo>

#include "codec.h"
#include "query.pb.h"

using std::cout;
using std::endl;

void testSerialize() {
  xlcomm::Query query;
  query.set_id(1);
  query.set_questioner(" ubuntu ");
  // query.set_question("How old are you?");

  std::string str;
  query.SerializeToString(&str);

  xlcomm::Query query2;
  query2.ParseFromString(str);
  cout << query2.id() << query2.questioner() << query2.question() << endl;
}

template <typename T>
void testDescriptor() {
  cout << "-------------------------------\n";
  std::string type_name = T::descriptor()->full_name();
  cout << type_name << endl;

  const google::protobuf::Descriptor* descriptor =
      google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(
          type_name);
  assert(descriptor == T::descriptor());
  cout << "FindMessageTypeByName() = " << descriptor << endl;
  cout << "T::descriptor()         = " << T::descriptor() << endl;
  cout << endl;

  const google::protobuf::Message* prototype =
      google::protobuf::MessageFactory::generated_factory()->GetPrototype(
          descriptor);
  assert(prototype == &T::default_instance());
  cout << "GetPrototype()        = " << prototype << endl;
  cout << "T::default_instance() = " << &T::default_instance() << endl;
  cout << endl;

  T* new_obj = dynamic_cast<T*>(prototype->New());
  T* new_obj2 = dynamic_cast<T*>(prototype->New());
  assert(new_obj != NULL);
  assert(new_obj != prototype);
  assert(typeid(*new_obj) == typeid(T::default_instance()));
  cout << "prototype->New() = " << new_obj << endl;
  cout << "prototype->New() = " << new_obj2 << endl;
  cout << endl;
  delete new_obj;
  delete new_obj2;
  cout << "-------------------------------\n";
}

int main() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;
  testSerialize();

  testDescriptor<xlcomm::Query>();
  testDescriptor<xlcomm::Answer>();

  google::protobuf::Message* newQuery = CreateMessage("xlcomm.Query");
  assert(newQuery != NULL);
  assert(typeid(*newQuery) == typeid(xlcomm::Query::default_instance()));
  cout << "CreateMessage(\"xlcomm.Query\") = " << newQuery << endl;

  google::protobuf::Message* newAnswer = CreateMessage("xlcomm.Answer");
  assert(newAnswer != NULL);
  assert(typeid(*newAnswer) == typeid(xlcomm::Answer::default_instance()));
  cout << "CreateMessage(\"xlcomm.Answer\") = " << newAnswer << endl;

  delete newQuery;
  delete newAnswer;

  puts("All pass!!!");

  google::protobuf::ShutdownProtobufLibrary();
}